# VUE Forms

# Forms Vue mastery

  • -> encapsulate all forms into components.
  • buld reusable components
  • default for input is text if nothing is declared

2 way to get data from input:

  • use v-model -> has 2-way binding
  • or @input-event-listener (might be good for validation)

# v-model

v-bind, creates a one-way binding, from the data to the template.

v-model is creating two-way data binding.

v-model is a combination of :value and @input

<input type="text" :value="name" @input="setName"/>
  • two-way data binding
 <label>EMAIL</label>
 <input type="email" required v-model="email" />
<label>Role:</label>
    <select v-model="role">
      <option value="developer">Web Developer</option>
      <option value="designer">Web Designer</option>
    </select>
# checkbox
   <div class="terms">
      <input type="checkbox" require v-model="terms" />
      <label>Accept terms and conditions</label>
    </div>
# multiple checkboxes with same v-model
  • adds value to the array
<div>
      <input type="checkbox" value="shaun" v-model="names" />
      <label>Shaun</label>
    </div>
    <div>
      <input type="checkbox" value="yoshi" v-model="names" />
      <label>yoshi</label>
    </div>
    <div>
      <input type="checkbox" value="mario" v-model="names" />
      <label>mario</label>
    </div>
# keyboard

-> access to event

<input type="text" v-model="tempSkill" @keyup="addSkill" />
//

methods: {
	addSkill(event) {
		console.log(event);
	},
},

# v-model-Modifiers

# .number

v-model.number is a modifier that typecasts the value as a number.

<input id="age" name="age" type="number" />

even with type="number", the value of HTML input elements always returns a string.

if you use a ref, no automaric type-conversion takes place

But with vue, this returns a number - with vue3:

<input v-model.number="age" type="number" />

-> forces a number

other modifiers:

# .lazy

  • don't update immedialtely

# .trim

trims extra whitespace on beginning/end (like using the trim() -function)


v-model works on <select>

<div >
      <label for="referrer">How did you hear about us?</label>
      <select id="referrer" name="referrer" v-model="referrer">
        <option value="google">Google</option>
        <option value="wom">Word of mouth</option>
        <option value="newspaper">Newspaper</option>
      </select>
</div>

# Radio and Checkboxes

for a single checkbox

<input
	type="checkbox"
	id="confirm-terms"
	name="confirm-terms"
	v-model="confirm"
/>

-> you get true or false

  • add a value-attribute and v-model to every checkbox

  • use an empty array for the data -> you get an array with the value of all the options

<div >
      <h2>What are you interested in?</h2>
      <div>
        <input
          id="interest-news"
          name="interest"
          type="checkbox"
          v-model="interest"
          value="News"
        />
        <label for="interest-news">News</label>
      </div>
      <div>
        <input
          id="interest-tutorials"
          name="interest"
          type="checkbox"
          v-model="interest"
          value="Tutorials"
        />
        <label for="interest-tutorials">Tutorials</label>
      </div>
      <div>
        <input
          id="interest-nothing"
          name="interest"
          type="checkbox"
          v-model="interest"
          value="Nothing"
        />
        <label for="interest-nothing">Nothing</label>
      </div>
    </div>

# Form Validation

validate on

  • submit method
  • every keystroke
  • wehenever an element looses focus ('blur') @blur="validateInput"
 <div class="form-control">
      <label for="user-name">Your Name</label>
      <input
        id="user-name"
        name="user-name"
        type="text"
        v-model.trim="userName"
        @blur="validateInput"
      />
      <p v-if="usernameValidity === 'invalid'">Please enter a valid name!</p>
    </div>
      
...

validateInput() {
      if (this.userName === '') {
        this.usernameValidity = 'invalid';
      } else {
        this.usernameValidity = 'valid';
      }
    }

# Build Custom Element -

# Binding to the value

you can use v-model on custom components. it uses a special prop "modelValue" and a special event "update:modelValue"

use props: ['modelValue'],

props: ['modelValue'],
emits: ['update:modelValue'],

in the custom element: eg.

# modelValue

By default in Vue 3, v-model expects a property named modelValue to be on your v-model-capable component.

export default {
  props: ['modelValue'],
  emits: ['update:modelValue'],
  data() {
    return {
      activeOption: this.modelValue
    };
  },
  methods: {
    activate(option) {
      this.activeOption = option;
      this.$emit('update:modelValue', option);
    }
  }
};

another example:

<template>
  <label v-if="label">{{ label }}</label>
  <input
    :value="modelValue"
    :placeholder="label"
    class="field"
  >
</template>

<script>
export default {
  props: {
    label: {
      type: String,
      default: ''
    },  
    modelValue: {
      type: [String, Number],
      default: ''
    }
  }
}
</script>

# Emitting update:modelValue

All components that are capable of being v-modeled have to emit an event in order for the parent to be able to catch the updates to that component’s data.

In Vue 3, by default all v-model contracts expect for your component to emit an update:modelValue event,

 <input
    :placeholder="label"
    :value="modelValue"
    @input="$emit('update:modelValue', $event.target.value)"
  />

# Passing $attrs

for: Attributes, classes & styles

  • when you pass down attributes, classes and styles from a parent to a child, Vue will attempt to automatically figure out where inside your template these attributes should be injected.

  • In single root components (components with a single wrapping element), Vue will inject all the attributes, classes and styles into the root element.

  • In multi-root components, Vue can’t figure out which one of the nodes, or fragments, it should inject the attributes to.

    -> you have to manually bind the $attrs object to the element.

<input
		v-bind="$attrs"
    class="field"
    :placeholder="label"
    :value="modelValue"
    @input="$emit('update:modelValue', $event.target.value)"
/>